package com.avidys.jwom.client;

import com.avidys.common.gwt.game.wom.model.LoginInfo;
import com.avidys.common.gwt.game.wom.model.LoginService;
import com.avidys.common.gwt.game.wom.model.LoginServiceAsync;
import com.avidys.common.gwt.game.wom.model.NotLoggedInException;
import com.avidys.common.gwt.game.wom.model.Server;
import com.avidys.common.gwt.game.wom.model.ServerService;
import com.avidys.common.gwt.game.wom.model.ServerServiceAsync;
import com.avidys.common.gwt.game.wom.model.User;
import com.avidys.common.gwt.net.Logging;
import com.avidys.common.gwt.ui.ButtonBar;
import com.avidys.common.gwt.ui.IButtonBar;
import com.google.gwt.core.client.Duration;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Jwom implements EntryPoint {
	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private static final String SERVER_ERROR = "An error occurred while "
			+ "attempting to contact the server. Please check your network "
			+ "connection and try again.";

	/**
	 * Create a remote service proxy to talk to the server-side Greeting
	 * service.
	 */
	private final ServerServiceAsync greetingService = GWT
			.create(ServerService.class);

	Test gamePanel; // WOMPanel
	AbsolutePanel root = RootPanel.get();

	DialogResults db = new DialogResults();
	ButtonBar bb = new ButtonBar(new buttonHandler(), new String[] {
		 "Add 1", "Test " + N, "List", "Game" });

	private LoginInfo loginInfo = null;
	private VerticalPanel loginPanel = new VerticalPanel();
	private Label loginLabel = new Label(
			"Please sign in to your Google Account to access the WoM application.");
	private Anchor signInLink = new Anchor("Sign In");

	public void onModuleLoad() {
		// Check login status using login service.
		LoginServiceAsync loginService = GWT.create(LoginService.class);
		loginService.login(GWT.getHostPageBaseURL(),
				new AsyncCallback<LoginInfo>() {
					public void onFailure(Throwable error) {
					}

					public void onSuccess(LoginInfo result) {
						loginInfo = result;
						if (loginInfo.isLoggedIn()) {
							loadGame();
						} else {
							loadLogin();
						}
					}
				});
	}

	private void loadLogin() {
		// Assemble login panel.
		loginPanel.setWidth("100%");
		loginPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

		signInLink.setHref(loginInfo.getLoginUrl());
		loginPanel.add(loginLabel);
		loginPanel.add(signInLink);
		root.add(loginPanel);
	}

	// private Anchor signInLink = new Anchor("Sign In");
	private Anchor signOutLink = new Anchor("Sign Out");

	private void loadGame() {
		// Set up sign out hyperlink.
		signOutLink.setHref(loginInfo.getLogoutUrl());

		// Create table for stock data.
		// stocksFlexTable.setText(0, 0, "Symbol");
		// stocksFlexTable.setText(0, 1, "Price");
		// stocksFlexTable.setText(0, 2, "Change");
		// stocksFlexTable.setText(0, 3, "Remove");

		// Assemble Main panel.
		gamePanel = new Test();
		root.add(gamePanel);

		// mainPanel.add(signOutLink);
		// mainPanel.add(stocksFlexTable);
		// mainPanel.add(addPanel);
		// mainPanel.add(lastUpdatedLabel);
	}

	private void handleError(Throwable error) {
		Window.alert(error.getMessage());
		if (error instanceof NotLoggedInException) {
			Window.Location.replace(loginInfo.getLogoutUrl());

			// root.add(new HTML("add failure "+caught.toString()));

		}
	}

	public void addServer(String url, String name, String desc) {
		db.startRun("create", "Create 1 row");
		Server s = new Server(new User(), url, name, desc);
		greetingService.addServer(s, new AsyncCallback() {
			
			public void onFailure(Throwable error) {
				handleError(error);
			}

			
			public void onSuccess(Object result) {
				db.showResult("row created");
			}
		});

	}

	protected static final int N = 100;
	int currentServer = 0;
	
	void createN() {

		db.startRun("Test "+N,"Creating "+N+" rows in DB.");
		Duration d;

		d = new Duration();
		int i;
		for (i = 0; i < N; i++) {
			Server s = new Server(new User(), urlField.getText(), "server " + 1, descField.getText());
			greetingService.addServer(s, new AsyncCallback() {
				public void onFailure(Throwable error) {
					handleError(error);
				}
				public void onSuccess(Object result) {
					db.add1(""+currentServer++);
				}
			});
		}
		int r = d.elapsedMillis();
		root.add(new HTML("Rounds" +N+"   Elapsed: " + r));
		Logging.info("Elapsed: " + r);
		db.showResult("Rounds" +N+"   Elapsed: " + r);
	}


	TextBox nameField = new TextBox();
	TextBox urlField = new TextBox();
	TextBox descField = new TextBox();

	public class Test extends Composite {

		Test() {

			// Create a handler for the sendButton and nameField
			class MyHandler implements ClickHandler, KeyUpHandler {
				/**
				 * Fired when the user clicks on the sendButton.
				 */
				public void onClick(ClickEvent event) {
					db.sendNameToServer();
				}

				/**
				 * Fired when the user types in the nameField.
				 */
				public void onKeyUp(KeyUpEvent event) {
					if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
						db.sendNameToServer();
					}
				}

			}

			nameField.setText("");

			// Focus the cursor on the name field when the app loads
			nameField.setFocus(true);
			nameField.selectAll();

			HorizontalPanel vp = new HorizontalPanel();
			nameField.addKeyUpHandler(new MyHandler());
			vp.add(nameField);
			vp.add(urlField);
			vp.add(descField);

			VerticalPanel panel = new VerticalPanel();
			panel.setWidth("100%");
			panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

			panel.add(vp);
			panel.add(bb);
			panel.add(signOutLink);

			initWidget(panel);
		}

	}

//	Game g = new Game();

	class buttonHandler implements IButtonBar {

		
		public void onButtonClicked(int lastButtonClickedInt,
				Button lastButtonClicked) {
			switch (lastButtonClickedInt) {
			case 0:
				addServer(urlField.getText(),nameField.getText(),descField.getText());
				break;
			case 1:
				createN();
				break;
			case 2:
				db.sendNameToServer();
				break;
			case 3:
//				g.show();
				break;
			}
		}
	}


	private void enableButtons() {
		//bb.setEnabledAll(true);
		//bb.setFocusAll(true);
	}

	private class DialogResults extends DialogBox {
		// Create the popup dialog box
		
		final Label textToServerLabel = new Label();
		final HTML serverResponseLabel = new HTML();
		final HTML pb = new HTML("");
		final Button closeButton = new Button("Close");

		public DialogResults() {
			// final DialogBox dialogBox = new DialogBox();
			setText("Remote Procedure Call");
			setAnimationEnabled(true);
			// We can set the id of a widget by accessing its Element
			closeButton.getElement().setId("closeButton");
			VerticalPanel dialogVPanel = new VerticalPanel();
			dialogVPanel.addStyleName("dialogVPanel");
			dialogVPanel.add(new HTML("<b>Sending name to the server:</b>"));
			dialogVPanel.add(textToServerLabel);
			dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
			dialogVPanel.add(serverResponseLabel);
			dialogVPanel.add(serverResponseLabel);
			pb.setWordWrap(true);
			dialogVPanel.add(pb);
			dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
			dialogVPanel.add(closeButton);
			setWidget(dialogVPanel);

			// Add a handler to close the DialogBox
			closeButton.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					hide();
					enableButtons();
				}

			});

		}

		public void add1(String string) {
			pb.setText(pb.getText()+string+", ");			
		}

		public void startRun(String title, String textToServer) {
			// bb.setEnabledAll(false);
			show();
			setText(title);
			textToServerLabel.setText(textToServer);
		}
		
		public void showResult(String string) {
			serverResponseLabel.setHTML(string);
			// bb.setEnabledAll(true);
		}

		/**
		 * Send the name from the nameField to the server and wait for a
		 * response.
		 */
		public void sendNameToServer() {
			show();
			//bb.setEnabledAll(false);
			String textToServer = nameField.getText();
			textToServerLabel.setText(textToServer);
			serverResponseLabel.setText("");
			greetingService.listServers(new AsyncCallback<Server[]>() {
				public void onFailure(Throwable caught) {
					// Show the RPC error message to the user
					setText("Remote Procedure Call - Failure");
					serverResponseLabel
							.addStyleName("serverResponseLabelError");
					serverResponseLabel.setHTML(SERVER_ERROR);
					center();
					closeButton.setFocus(true);
				}

				public void onSuccess(Server[] ls) {
					setText("Remote Procedure Call");
					serverResponseLabel
							.removeStyleName("serverResponseLabelError");
					StringBuffer ns = new StringBuffer();
					if (ns == null)
						ns.append("no results<br>");
					else
						for (Server s : ls) {
							ns.append(s.name + "<br>");
						}
					serverResponseLabel.setHTML(ns.toString());
					center();
					closeButton.setFocus(true);
				}
			});
		}
	}
}
